package  com.microstrategy.web;

import com.microstrategy.web.app.AbstractExternalSecurity;
import com.microstrategy.web.app.ExternalSecurity;
import com.microstrategy.web.app.LoginForm;
import com.microstrategy.web.app.beans.EnumServletEvents;
import com.microstrategy.web.beans.GenericWebEvent;
import com.microstrategy.web.beans.RequestKeys;
import com.microstrategy.web.objects.WebIServerSession;
import com.microstrategy.web.objects.WebObjectsFactory;
import com.microstrategy.web.platform.ContainerServices;


public class MyExternalSecurity extends AbstractExternalSecurity {
	
	/**
	 * This is the value of the URL Parameter ({@link PARAM_NAME_ERR_TYPE})
	 * that indicates an authorization failure.
	 */
	public static final String PARAM_VALUE_ERR_TYPE_AUTHORIZE = "authorize";

	/**
	 * This is the value of the URL Parameter ({@link PARAM_NAME_ERR_TYPE})
	 * that indicates an authentication failure.
	 */
	public static final String PARAM_VALUE_ERR_TYPE_AUTHENTICATE = "authenticate";

	public static final String USER_AUTHENTICATION_INFO = "UserInfo";
	/**
	 * This is the name of the URL Parameter that  indicates the type of custom
	 * error failure (either authentication or authorization).
	 */
	public static final String PARAM_NAME_ERR_TYPE = "errType";
	

	// This defines the path to our custom error page...
	private static final String URL_PATH_TO_ERROR = "../jsp/MyError.jsp";
	private final String CustomizeLoginPage = "/jsp/MyLogin.jsp";

	// ******************************************************
	// *  C o n s t r u c t o r s . . .
	// ******************************************************

	/**
	 * This is the no-args constructor for the Sample External Security class.
	 * As there is no instance or class data members, this is essentially
	 * empty.
	 */
	public MyExternalSecurity() {
		super();
		System.out.println(" ExternalSecurity: This is init MyExternalSecurity instance!");
	}

	// ******************************************************
	// *  I n t e r f a c e   M e t h o d s . . .
	// ******************************************************

	/**
	 * Indicates how this External Security object wants to handle the
	 * authentication request.  For our implementation, it is based on global
	 * settings managed by the {@link DemoManager} class.
	 *
	 * @param reqKeys A {@link RequestKeys} instance to retrieve HTTP request
	 * 		  data.
	 * @param cntSvcs A {@link ContainerServices} instance to retrieve all
	 * 		  application- and session-wide data.
	 * @param reason an <code>int</code> value representing the reason why
	 * 		  authentication request is being made.  (Should be one of {@link
	 * 		  ExternalSecurity#INVALID_CREDENTIALS},   {@link
	 * 		  ExternalSecurity#NO_SESSION_FOUND}, or {@link
	 * 		  ExternalSecurity#SESSION_CLOSED}).
	 *
	 * @return An <code>int</code> value indicating how the session handling
	 * 		   should be processed.  Should be one of {@link
	 * 		   ExternalSecurity#USE_CUSTOM_LOGIN_PAGE}, {@link
	 * 		   ExternalSecurity#USE_MSTR_DEFAULT_LOGIN} or {@link
	 * 		   ExternalSecurity#COLLECT_SESSION_NOW}.
	 */
	public int handlesAuthenticationRequest(RequestKeys reqKeys,
						ContainerServices cntSvcs, int reason) 
	{
	
		System.out.println("ExternalSecurity: Called the handlesAuthenticationRequest");
		int __result = -1;

		//Indicate that we want MSTR Web to collect a Session right now!
			
		if(cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO)!= null)
		{
			Credential userInfo =(Credential) cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO);
			boolean isValidUser = true;
		        if( isValidUser )
		            __result = ExternalSecurity.COLLECT_SESSION_NOW;
		        else
		            __result = ExternalSecurity.USE_CUSTOM_LOGIN_PAGE;
	
	        }
		// Indicate that we want to send people to a custom page...
		else
		{
			__result = ExternalSecurity.USE_CUSTOM_LOGIN_PAGE;
		}	
		// Use the standard MSTR Web login page...
		//__result = ExternalSecurity.USE_MSTR_DEFAULT_LOGIN;
	        return __result;
	}

	/**
	 * Return either a set of credentials or an existing Intelligence Server
	 * session. Both are returned in the form of a {@link
	 * com.microstrategy.web.objects.WebIServerSession} object.
	 *
	 * @param reqKeys A {@link RequestKeys} instance
	 * @param cntSvcs A {@link ContainerServices} instance
	 *
	 * @return A {@link com.microstrategy.web.objects.WebIServerSession} object
	 * 		   to use as session for the current user request.
	 */
	public WebIServerSession getWebIServerSession(RequestKeys reqKeys,  ContainerServices cntSvcs) 
	{
           System.out.println("ExternalSecurity: called getWebIServerSession. ");   
           WebIServerSession __result = null; 
           
           if(cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO)!= null)
	   {
		Credential userInfo =(Credential) cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO);  	
		    __result =  WebObjectsFactory.getInstance().getIServerSession();
		    __result.setLogin(userInfo.getMSTRSession().getLogin());
		    __result.setPassword(userInfo.getMSTRSession().getLogin());		    
		    __result.setServerName(userInfo.getMSTRSession().getServerName());
		    __result.setServerPort(0);
			String projectName = reqKeys.getValue("Project",0);
	    	if(projectName!=null){	    		
	    		__result.setProjectName(projectName);
	    	}
	    	userInfo.setMSTRSession(__result);
 	   } 
 	   //return (__result = pUser.getMSTRSession());
 	   return __result;
	}
	

	/**
	 * Returns the URL of a custom page that will handle the authentication
	 * request, in case the <code>handlesAuthenticationRequest()</code> method
	 * returned <code>USE_CUSTOM_LOGIN_PAGE</code>
	 *
	 * @param originalURL The original url that was being called when the
	 * 		  authentication request came up
	 * @param desiredServer The desired Intelligence Server machine name.
	 * @param desiredPort The desired port of the Intelligence Server.
	 * @param desiredProject The desired project to connect to.
	 *
	 * @return A <code>String</code> value with the url where the use should be
	 * 		   redirected to. <p>
	 */
	public String getCustomLoginURL(String originalURL, 
					String desiredServer,
					int desiredPort, 
					String desiredProject) 
	{
	
	System.out.println("ExternalSecurity: construct the custom user login url");
	// Construct the URL
	String __result = null;
	//return (__result = CustomLoginForm.buildLoginURL(originalURL, desiredServer, desiredPort, desiredProject));
	return  CustomizeLoginPage;	
	}

	/**
	 * Determines if the user is authorized to perform the incoming request.
	 *
	 * @param reqKeys A {@link RequestKeys} instance
	 * @param cntSvcs A {@link ContainerServices} instance
	 * @param user The {@link WebIServerSession} instance representing the
	 * 		  current user for this specific request.
	 *
	 * @return <code>true</code> if the request is authorized. Otherwise,
	 * 		   returns <code>false</code>.
	 */
	public boolean isRequestAuthorized(RequestKeys reqKeys, ContainerServices cntSvcs, WebIServerSession user)
	{
		System.out.println("ExternalSecurity: Call isRequestAuthorized!");
		// Initialize a logger object...
		boolean __result = false;
		if(cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO) == null) return false;
		if (isLogoutRequest(reqKeys))  
		{
			cntSvcs.setSessionAttribute(USER_AUTHENTICATION_INFO, null); 
			//releaseISeverSession. 
 	   		return (__result = true);
	        }
		else
		{// do some requestCheck job.
			Credential userInfo =(Credential) cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO); 
					
			return (__result = true);
		}
	}


	/**
	 * Manipulates the already created {@link WebIServerSession} instance and
	 * modifies it, if desired.
	 *
	 * @param reqKeys A {@link RequestKeys} instance
	 * @param cntSvcs A{@link ContainerServices} instance
	 * @param loginForm The {@link LoginForm} instance containing information
	 * 		  from the Web Universal Login Form.
	 * @param reason <code>int</code> value indicating why this authentication
	 * 		  request was required.
	 *
	 * @return a boolean value indicating the status of the form {@link
	 * 		   LoginForm#getFormStatus}.
	 */
	public boolean processMSTRLoginForm(RequestKeys reqKeys,
					ContainerServices cntSvcs,
					LoginForm loginForm, int reason) 
	{
		 
         System.out.println("ExternalSecurity: ProcessMstrLoginForm ... ");
	 boolean __result = false;
	 
	 if(cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO)== null) return false;
	
	 Credential userInfo =(Credential) cntSvcs.getSessionAttribute(USER_AUTHENTICATION_INFO);  	
 	
	 if( userInfo.getUserName().equals(loginForm.getLoginName())== false)
	 {
	 	loginForm.setFormErrorMessage("Invalid User Credentail");	
	  	loginForm.setFormStatus(false);
   	     	return (__result = false);
	 }
	 if (userInfo.getMSTRSession() == null) {
		// Set the error message...
		 loginForm.setFormErrorMessage("Your User account is not configured to " +
	 			  "grant you access to the MicroStrategy Web application.  " +
				  "Please contact your Administrator.");

		// Set the status of the form
		loginForm.setFormStatus(false);
		return (__result = false);
	}
	 
	
	loginForm.setWebIServerSession(userInfo.getMSTRSession());
	loginForm.setFormStatus(true);
	return (__result = true);
 	}
	/**
	 * Once it has been determined the request has failed, this method will
	 * provide the URL information where the user should be taken next.
	 *
	 * @param reqType an <code>int</code> value indicating which request was
	 * 		  the one that failed: <code>AUTHENTICATION_REQUEST</code> or
	 * 		  <code>AUTHORIZIATION_REQUEST</code>
	 * @param cntrSvcs {@link ContainerServices} initialized instance
	 *
	 * @return a <code>String</code> with the URL to use for redirecting the
	 * 		   user.
	 */
	public String getFailureURL(int reqType, ContainerServices cntrSvcs) 
	{
		System.out.println("ExternalSecurity: To get the failure URL");
		String __result = null;
		__result = URL_PATH_TO_ERROR + "?" + 
		            PARAM_NAME_ERR_TYPE + "=" +
			   ((reqType == ExternalSecurity.AUTHENTICATION_REQUEST)? PARAM_VALUE_ERR_TYPE_AUTHENTICATE: PARAM_VALUE_ERR_TYPE_AUTHORIZE);
		System.out.println("FailureURL: " + __result);
		//return URL_PATH_TO_ERROR;
		return CustomizeLoginPage;
	}

	// ******************************************************
	// *  P r i v a t e   M e t h o d s . . .
	// ******************************************************
	// This utility method tests to see if the current incoming request is a
	// request to logout of out MSTR Web Universal...
	private boolean isLogoutRequest(RequestKeys reqKeys) {
		System.out.println("ExternalSecurity: isLogoutRequest!");
		// First, get the value of the evt key...
		String strValue = reqKeys.getValue(GenericWebEvent.URL_EVENT_NAME);

		if ((strValue == null) || strValue.equals("")) {
			return false;
		}

		// Try to convert it to a number...
		int intValue = -1;

		try {
			intValue = Integer.parseInt(strValue);
		} catch (NumberFormatException nfe) {
			return false;
		}

		// Is it the MSTR Logout event code?
		if (intValue == EnumServletEvents.WebEventLogout) {
			return true;
		}

		return false;
	}
}
